<!DOCTYPE html>
<html lang="en-us">
<head><head>
    <meta name="referrer" content="no-referrer"/>
    <meta name="google-site-verification" content="9vIieCe-Qpd78QOmBl63rGtIVbhY6sYyuxX3j8XWBA4" />
    <meta name="baidu-site-verification" content="LRrmH41lz7" />
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="description" content="在微服务架构中，api网关是一个十分重要的存在。一方面它为外部的流量访问提供了统一的入口，使得可以方便的进行防火墙的策略实施；另一方面，可以在网关处进行流量控制、认证、授权、灰度、日志收集、性能分析等各种高级功能，使得业务功能与非功能有效解耦，给予了系统架构更大的灵活性。本系列文章尝试分析目前主流的云原生微服务网关，并比较各自的优劣。">
    
    <meta name="keyword"  content="暴走的初号机, shinji3887, 暴走的初号机的网络日志, 暴走的初号机的博客, shinji3887 Blog, 博客, 个人网站, 互联网, Web, 云原生, PaaS, Istio, Kubernetes, 微服务, Microservice">
    <link rel="shortcut icon" href="/img/favicon.ico">

    <title>构建云原生微服务网关系列-篇一：Ambassador-同步率400%</title>

    <link rel="canonical" href="/post/cloud-native-api-gateway-part-1/">

    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/iDisqus.min.css"/>
	
    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/bootstrap.min.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/hux-blog.min.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/syntax.css">

    
    <link rel="stylesheet" href="https://lupeier.cn-sh2.ufileos.com/zanshang.css">

    
    <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css">
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/jquery.min.js"></script>
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/bootstrap.min.js"></script>
    
    
    <script src="https://lupeier.cn-sh2.ufileos.com/hux-blog.min.js"></script>
</head>
</head>

<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
    <div class="container-fluid">
        
        <div class="navbar-header page-scroll">
            <button type="button" class="navbar-toggle">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">L&#39;s Blog</a>
        </div>

        
        
        <div id="huxblog_navbar">
            <div class="navbar-collapse">
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="/">Home</a>
                    </li>
                    
                    <li>
                        <a href="categories/tech">tech</a>
                    </li>
                    
                    <li>
                        <a href="categories/tips">tips</a>
                    </li>
                    
                    <li>
                        <a href="/about">About</a>
                    </li>
                    
                </ul>
            </div>
        </div>
        
    </div>
    
</nav>
<script>
    
    
    
    var $body   = document.body;
    var $toggle = document.querySelector('.navbar-toggle');
    var $navbar = document.querySelector('#huxblog_navbar');
    var $collapse = document.querySelector('.navbar-collapse');

    $toggle.addEventListener('click', handleMagic)
    function handleMagic(e){
        if ($navbar.className.indexOf('in') > 0) {
        
            $navbar.className = " ";
            
            setTimeout(function(){
                
                if($navbar.className.indexOf('in') < 0) {
                    $collapse.style.height = "0px"
                }
            },400)
        }else{
        
            $collapse.style.height = "auto"
            $navbar.className += " in";
        }
    }
</script>




<style type="text/css">
    header.intro-header{
        background-image: url('https://lupeier.cn-sh2.ufileos.com/blur-daylight-depth-of-field-10678.jpg')
    }
</style>
<header class="intro-header" >
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <div class="post-heading">
                    <div class="tags">
                       
                       <a class="tag" href="/tags/cloud-native" title="Cloud Native">
                           Cloud Native
                        </a>
                        
                       <a class="tag" href="/tags/api-gateway" title="Api Gateway">
                           Api Gateway
                        </a>
                        
                    </div>
                    <h1>构建云原生微服务网关系列-篇一：Ambassador</h1>
                    <h2 class="subheading"></h2>
                    <span  class="meta">Posted by 陆培尔 on Tuesday, July 30, 2019
                        
                    </span>
					<br>
                </div>
            </div>
        </div>
    </div>
</header>




<article>
    <div class="container">
        <div class="row">

            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                post-container">

        		
                        <header>
                        <h2>TOC</h2>
                        </header>
                        <nav id="TableOfContents">
  <ul>
    <li>
      <ul>
        <li><a href="#网关选型标准">网关选型标准</a></li>
        <li><a href="#什么是ambassador">什么是Ambassador？</a></li>
        <li><a href="#ambassador架构">Ambassador架构</a></li>
        <li><a href="#扩展性和可用性">扩展性和可用性</a></li>
        <li><a href="#与其他网关产品比较">与其他网关产品比较</a></li>
        <li><a href="#istio">Istio</a></li>
        <li><a href="#安装ambassador">安装Ambassador</a></li>
        <li><a href="#用例1边缘南北路由">用例1：边缘（南/北）路由</a></li>
        <li><a href="#用例2内部南北路由">用例2：内部（南/北）路由</a></li>
        <li><a href="#用例3内部东西路由">用例3：内部（东/西）路由</a></li>
        <li><a href="#用例4流量镜像">用例4：流量镜像</a></li>
        <li><a href="#配置">配置</a></li>
        <li><a href="#ambassador的不足">Ambassador的不足</a></li>
        <li><a href="#总结">总结</a></li>
        <li><a href="#参考文献">参考文献</a></li>
      </ul>
    </li>
  </ul>
</nav>
        		
        		<blockquote>
<p>在微服务架构中，api网关是一个十分重要的存在。一方面它为外部的流量访问提供了统一的入口，使得可以方便的进行防火墙的策略实施；另一方面，可以在网关处进行流量控制、认证、授权、灰度、日志收集、性能分析等各种高级功能，使得业务功能与非功能有效解耦，给予了系统架构更大的灵活性。本系列文章尝试分析目前主流的云原生微服务网关，并比较各自的优劣。</p>
</blockquote>
<h3 id="网关选型标准">网关选型标准</h3>
<p>其实kubernetes本身有一个ingress controller，基于nginx或haproxy等7层代理进行流量的转发。不过ingress只能进行简单的反向代理，不支持流控、灰度、认证、授权等网关必备的功能。所以一般意义认为，ingress是一个7层http代理，而非api网关。本系列主要分析ambassador、traefik、kong等具备<strong>微服务</strong>所需能力的网关产品。</p>
<h3 id="什么是ambassador">什么是Ambassador？</h3>
<p>这里引用官网的一段描述</p>
<blockquote>
<p>Ambassador是一个基于envoy proxy构建的，kubernetes原生的开源微服务网关。Ambassador在构建之初就致力于支持多个独立的团队，这些团队需要为最终用户快速发布、监控和更新服务。Ambassador还可以用来处理Kubernetes ingress和负载均衡的能力。</p>
</blockquote>
<p>注意这里的几个关键词：<strong>envoy</strong>，<strong>kubernetes原生</strong>，<strong>微服务</strong>。现在市面上网关产品不少，不过kubernetes原生的产品倒真的不多。传统的网关产品一般是基于rest api或者yaml文件来进行配置（谁让这些老大哥出来的早呢，他们火的时候k8还没出来呢），而ambassador完全基于k8标准的annotation或者CRD来进行各类配置，没错，非常的<strong>native</strong>。</p>
<h3 id="ambassador架构">Ambassador架构</h3>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-0dcae8cb18297b27.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
如果是了解istio的同学，看到这张图会有十分熟悉的感觉，没错，Ambassador也是具有控制平面和数据平面的。数据平面自然是老伙计envoy，Ambassador的控制平面负责监听k8中的service资源的变化，并将配置下发envoy，实际的流量转发通过envoy来完成。（感觉就是一个轻量级的istio）</p>
<p>具体流程如下：</p>
<ol>
<li>服务所有者在kubernetes manifests中定义配置(通过annotation或者CRD)。</li>
<li>当manifest应用到集群时，kubernetes api会将更改通知Ambassador。</li>
<li>Ambassador解析更改并将配置转换为一种中间语义。envoy的配置由该IR生成。</li>
<li>新的配置通过基于gRPC的聚合发现服务（ADS）API传递给envoy。</li>
<li>流量通过重新配置的envoy，而不会断开任何连接。</li>
</ol>
<h3 id="扩展性和可用性">扩展性和可用性</h3>
<p>Ambassador依靠Kubernetes实现扩展、高可用性和持久性。所有Ambassador配置都直接存储在Kubernetes中（etcd）；没有数据库。Ambassador被打包成一个单独的容器，其中包含控制平面和一个Ambassador代理实例。默认情况下，Ambassador部署为kubernetes deployment，可以像其他kubernetes deployment一样进行扩展和管理。</p>
<h3 id="与其他网关产品比较">与其他网关产品比较</h3>
<p>目前主流的网关产品可以分为三类：</p>
<ul>
<li>托管的api网关，比如 <a href="https://aws.amazon.com/api-gateway/">Amazon API gateway</a></li>
<li>传统的api网关，比如 <a href="https://getkong.org/">Kong</a></li>
<li>7层代理，比如 <a href="https://traefik.io/">Traefik</a>, <a href="http://nginx.org/">NGINX</a>, <a href="http://www.haproxy.org/">HAProxy</a>, or <a href="https://www.envoyproxy.io/">Envoy</a>, 或者是基于这些代理的 Ingress controllers</li>
</ul>
<p>所有这些托管的和传统的api网关的问题是：</p>
<ul>
<li>不是自服务的。传统API网关上的管理接口不是为开发人员自服务而设计的，为开发人员提供的安全性和可用性有限。</li>
<li>不是kubernetes原生的。它们通常使用REST APIs进行配置，这使得采用云原生模式（如Gitops和声明式配置）变得很困难。</li>
<li>为api管理而设计，而非微服务。</li>
</ul>
<p>一般来说，7层代理可以用作API网关，但需要额外的定制开发来支持微服务用例。事实上，许多API网关都将API网关所需的附加功能打包在L7代理之上。Ambassador使用envoy，而kong使用nginx。</p>
<h3 id="istio">Istio</h3>
<p>Istio是一个基于Envoy的开源服务网格。 服务网格用于管理东/西流量，而API网关用于管理南/北流量。 一般来说，我们发现南/北流量与东/西流量有很大不同（比如说，在南北流量中你无法控制客户端）。</p>
<h3 id="安装ambassador">安装Ambassador</h3>
<p>安装非常的简单，直接使用helm安装。如果对于helm还不是很了解，可以参考我之前的文章 <a href="https://www.jianshu.com/p/290f27841b8d">helm介绍</a>。
使用helm安装只需要执行如下命令：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">helm install --name my-release stable/ambassador
</code></pre></div><p> 这边插播一下，推荐使用微软azure的charts镜像<code>http://mirror.azure.cn/kubernetes/charts/</code>，基本和官方的同步，且可以正常访问，阿里云的charts不知道为什么更新很不及时。
安装完后可以看到有两个pods</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
ambassador-3655608000-43x86   1/1       Running   <span style="color:#ae81ff">0</span>          2m
ambassador-3655608000-w63zf   1/1       Running   <span style="color:#ae81ff">0</span>          2m
</code></pre></div><p>都是running状态，这样ambassador就安装完成了
接下来我们部署一下官网的应用</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml">---
<span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
<span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Service</span>
<span style="color:#f92672">metadata</span>:
  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">tour</span>
  <span style="color:#f92672">annotations</span>:
    <span style="color:#f92672">getambassador.io/config</span>: |<span style="color:#e6db74">
</span><span style="color:#e6db74">      ---
</span><span style="color:#e6db74">      apiVersion: ambassador/v1
</span><span style="color:#e6db74">      kind: Mapping
</span><span style="color:#e6db74">      name: tour-ui_mapping
</span><span style="color:#e6db74">      prefix: /
</span><span style="color:#e6db74">      service: tour:5000
</span><span style="color:#e6db74">      ---
</span><span style="color:#e6db74">      apiVersion: ambassador/v1
</span><span style="color:#e6db74">      kind: Mapping
</span><span style="color:#e6db74">      name: tour-backend_mapping
</span><span style="color:#e6db74">      prefix: /backend/
</span><span style="color:#e6db74">      service: tour:8080
</span><span style="color:#e6db74">      labels:
</span><span style="color:#e6db74">        ambassador:
</span><span style="color:#e6db74">          - request_label:
</span><span style="color:#e6db74">            - backend</span>      
<span style="color:#f92672">spec</span>:
  <span style="color:#f92672">ports</span>:
  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">ui</span>
    <span style="color:#f92672">port</span>: <span style="color:#ae81ff">5000</span>
    <span style="color:#f92672">targetPort</span>: <span style="color:#ae81ff">5000</span>
  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">backend</span>
    <span style="color:#f92672">port</span>: <span style="color:#ae81ff">8080</span>
    <span style="color:#f92672">targetPort</span>: <span style="color:#ae81ff">8080</span>
  <span style="color:#f92672">selector</span>:
    <span style="color:#f92672">app</span>: <span style="color:#ae81ff">tour</span>
---
<span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">apps/v1</span>
<span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Deployment</span>
<span style="color:#f92672">metadata</span>:
  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">tour</span>
<span style="color:#f92672">spec</span>:
  <span style="color:#f92672">replicas</span>: <span style="color:#ae81ff">1</span>
  <span style="color:#f92672">selector</span>:
    <span style="color:#f92672">matchLabels</span>:
      <span style="color:#f92672">app</span>: <span style="color:#ae81ff">tour</span>
  <span style="color:#f92672">strategy</span>:
    <span style="color:#f92672">type</span>: <span style="color:#ae81ff">RollingUpdate</span>
  <span style="color:#f92672">template</span>:
    <span style="color:#f92672">metadata</span>:
      <span style="color:#f92672">labels</span>:
        <span style="color:#f92672">app</span>: <span style="color:#ae81ff">tour</span>
    <span style="color:#f92672">spec</span>:
      <span style="color:#f92672">containers</span>:
      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">tour-ui</span>
        <span style="color:#f92672">image</span>: <span style="color:#ae81ff">quay.io/datawire/tour:ui-0.2.4</span>
        <span style="color:#f92672">ports</span>:
        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">http</span>
          <span style="color:#f92672">containerPort</span>: <span style="color:#ae81ff">5000</span>
      - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">quote</span>
        <span style="color:#f92672">image</span>: <span style="color:#ae81ff">quay.io/datawire/tour:backend-0.2.4</span>
        <span style="color:#f92672">ports</span>:
        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">http</span>
          <span style="color:#f92672">containerPort</span>: <span style="color:#ae81ff">8080</span>
        <span style="color:#f92672">resources</span>:
          <span style="color:#f92672">limits</span>:
            <span style="color:#f92672">cpu</span>: <span style="color:#e6db74">&#34;0.1&#34;</span>
            <span style="color:#f92672">memory</span>: <span style="color:#ae81ff">100Mi</span>
</code></pre></div><p>这个pod里面有两个容器，分别是前端的ui以及后端的backend。注意annotation里面的<code>getambassador.io/config</code>部分，这就是ambassador的配置了，分别定义了两个注释，kind是<code>Mapping</code>，定义了前后端的匹配路径，服务名称及端口。这个配置的意思是，凡是匹配上<code>/</code>的，全部走tour的5000端口，凡是匹配上<code>/backend</code>的，全部走tour的8080端口（对应的就是tour的service配置）。也可以使用CRD方式配置，ambassador已经默认创建了一组crd</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash"><span style="color:#f92672">[</span>root@MiWiFi-R1CM-srv zuul<span style="color:#f92672">]</span><span style="color:#75715e"># kubectl get crds|grep ambassador</span>
authservices.getambassador.io                  2019-07-27T11:40:58Z
consulresolvers.getambassador.io               2019-07-27T11:40:58Z
kubernetesendpointresolvers.getambassador.io   2019-07-27T11:40:58Z
kubernetesserviceresolvers.getambassador.io    2019-07-27T11:40:58Z
mappings.getambassador.io                      2019-07-27T11:40:58Z
modules.getambassador.io                       2019-07-27T11:40:58Z
ratelimitservices.getambassador.io             2019-07-27T11:40:58Z
tcpmappings.getambassador.io                   2019-07-27T11:40:58Z
tlscontexts.getambassador.io                   2019-07-27T11:40:58Z
tracingservices.getambassador.io               2019-07-27T11:40:58Z
</code></pre></div><p>其中mapping就是核心资源，用于路由的转发配置，下面是一个mapping资源配置示例</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
<span style="color:#f92672">items</span>:
- <span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">getambassador.io/v1</span>
  <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Mapping</span>
  <span style="color:#f92672">metadata</span>:
    <span style="color:#f92672">annotations</span>:
      <span style="color:#f92672">kubectl.kubernetes.io/last-applied-configuration</span>: |<span style="color:#e6db74">
</span><span style="color:#e6db74">        </span>        {<span style="color:#e6db74">&#34;apiVersion&#34;</span>:<span style="color:#e6db74">&#34;getambassador.io/v1&#34;</span>,<span style="color:#e6db74">&#34;kind&#34;</span>:<span style="color:#e6db74">&#34;Mapping&#34;</span>,<span style="color:#e6db74">&#34;metadata&#34;</span>:{<span style="color:#e6db74">&#34;annotations&#34;</span>:{},<span style="color:#e6db74">&#34;name&#34;</span>:<span style="color:#e6db74">&#34;nginx&#34;</span>,<span style="color:#e6db74">&#34;namespace&#34;</span>:<span style="color:#e6db74">&#34;default&#34;</span>},<span style="color:#e6db74">&#34;spec&#34;</span>:{<span style="color:#e6db74">&#34;prefix&#34;</span>:<span style="color:#e6db74">&#34;/nginx&#34;</span>,<span style="color:#e6db74">&#34;service&#34;</span>:<span style="color:#e6db74">&#34;nginx:80&#34;</span>}}
    <span style="color:#f92672">creationTimestamp</span>: <span style="color:#e6db74">&#34;2019-07-27T13:36:38Z&#34;</span>
    <span style="color:#f92672">generation</span>: <span style="color:#ae81ff">1</span>
    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default</span>
    <span style="color:#f92672">resourceVersion</span>: <span style="color:#e6db74">&#34;420594&#34;</span>
    <span style="color:#f92672">selfLink</span>: <span style="color:#ae81ff">/apis/getambassador.io/v1/namespaces/default/mappings/nginx</span>
    <span style="color:#f92672">uid</span>: <span style="color:#ae81ff">8f1f4d33-b073-11e9-be4c-0800279f163b</span>
  <span style="color:#f92672">spec</span>:
    <span style="color:#f92672">prefix</span>: <span style="color:#ae81ff">/nginx</span>
    <span style="color:#f92672">service</span>: <span style="color:#ae81ff">nginx:80</span>
<span style="color:#f92672">kind</span>: <span style="color:#ae81ff">List</span>
<span style="color:#f92672">metadata</span>:
  <span style="color:#f92672">resourceVersion</span>: <span style="color:#e6db74">&#34;&#34;</span>
  <span style="color:#f92672">selfLink</span>: <span style="color:#e6db74">&#34;&#34;</span>
</code></pre></div><p>一旦你修改了service里面的annotation设置，ambassador的控制面会自动将变更下发给envoy，全程不需要中断服务。（也要感谢envoy强大的xDS API）</p>
<p>下面我们来看一下Ambassador的几个使用场景：</p>
<h3 id="用例1边缘南北路由">用例1：边缘（南/北）路由</h3>
<p>这个是平时最常见的使用场景，网关位于整个集群的入口处，统一去做一些流控、鉴权等方面的工作：
<img src="https://upload-images.jianshu.io/upload_images/14871146-45238040cc6650c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
该场景的关注点在于：</p>
<ul>
<li>控制/路由入口流量的能力</li>
<li>卸载请求
<ul>
<li>认证（比如要求所有入口流量都必须要进过认证）</li>
<li>加密（TLS终端及传输加密）</li>
<li>重试及超时</li>
</ul>
</li>
</ul>
<p>saas service中的真实用例：
<img src="https://upload-images.jianshu.io/upload_images/14871146-7db0c08aafed66b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="saas.png"></p>
<h3 id="用例2内部南北路由">用例2：内部（南/北）路由</h3>
<p>通常来说，企业内部的系统架构会比较复杂，会有多集群或者多租户，比如一个kubernetes的集群和一个vm的集群（可能是openstack），那么在集群之间的流量就是内部的南/北流量，集群之间的流量交互可以通过ambassador完成。
<img src="https://upload-images.jianshu.io/upload_images/14871146-90750413b7c7e9f5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
此场景的关注点在于：</p>
<ul>
<li>控制/路由多租户流量的能力</li>
<li>卸载请求
<ul>
<li>匹配（基于headers）</li>
<li>重试及超时</li>
</ul>
</li>
</ul>
<p>saas service中的真实用例：
<img src="https://upload-images.jianshu.io/upload_images/14871146-23acd24daab3455b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h3 id="用例3内部东西路由">用例3：内部（东/西）路由</h3>
<p>这个场景中Ambassador已经作为集群内部东西向流量的代理了，配合它自己的控制平面，有点service mesh的意思了。区别在于，Ambassador在这个集群里是处于一个中心节点的位置（一个或一组ambassador实例），属于server proxy的范畴，而不是service mesh里面的client proxy（sidecar）。这种架构其实和传统的esb更加的接近。
<img src="https://upload-images.jianshu.io/upload_images/14871146-8cec66e2dc3b82c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
此场景关注点：</p>
<ul>
<li>控制/路由任意流量的能力（南北向+东西向）</li>
<li>卸载请求
<ul>
<li>服务发现</li>
<li>负载均衡</li>
<li>访问控制</li>
</ul>
</li>
</ul>
<p>大家可以看到，已经非常接近于service mesh的能力了（也许ambassador以后也会出一个service mesh产品？）</p>
<p>saas service的真实用例：
<img src="https://upload-images.jianshu.io/upload_images/14871146-605fcdf1a7987640.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png">
service mesh的真实用例（与istio集成）：
<img src="https://upload-images.jianshu.io/upload_images/14871146-dbefbeb1c9fcf405.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h3 id="用例4流量镜像">用例4：流量镜像</h3>
<p>此场景中可以把流量复制一份到其他服务中（影子流量），通常用于监控、测试等场景
<img src="https://upload-images.jianshu.io/upload_images/14871146-85a3899f164466c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<ul>
<li>测试代码、发布包的能力</li>
<li>利用真实的流量/负载</li>
<li>最小化重复资源</li>
</ul>
<blockquote>
<p>注意：上面所描述的几个典型场景其实不光可以使用Ambassador，而是适用于各类使用api gateway或者proxy的场景。</p>
</blockquote>
<h3 id="配置">配置</h3>
<p>Ambassador不同版本之间配置方式的变更如下图所示,configmap方式是早期使用方式，目前已经被废弃了，现在更推荐使用CRD方式。
<img src="https://upload-images.jianshu.io/upload_images/14871146-d2aac8fb2c0cbeda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h4 id="加密的配置方式">加密的配置方式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-f9231001054176b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h4 id="认证的配置方式">认证的配置方式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-38b74b7b5ed93f2e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h4 id="路由的配置方式">路由的配置方式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-64fc6ccdef6a0386.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h4 id="跟踪的配置方式">跟踪的配置方式</h4>
<p><img src="https://upload-images.jianshu.io/upload_images/14871146-2ed98f1ea3c98531.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p>
<h3 id="ambassador的不足">Ambassador的不足</h3>
<p>Ambassador和同类的网关产品类似，分为社区版及商业版，社区版提供了最基础的路由、限速、TLS加密、跟踪、认证（需要自己实现external third party authentication service）等能力，但是微服务网关中十分重要的OAuth2集成认证、RBAC、custom filter等功能都是需要在pro版中才能实现，这是比较遗憾的一点。尤其是custom filter，根据我们目前的经验，一个能力完整、功能丰富的微服务网关，必然会引入custom filter。而custom filter也需要使用go进行编写，对于不熟悉go的开发人员来说也会比较痛苦。</p>
<h3 id="总结">总结</h3>
<p>Ambassador作为一个较新推出的开源微服务网关产品，与kubernetes结合的相当好，基于annotation或CRD的配置方式与k8s浑然一体，甚至让人感觉这就是k8s自身功能的一部分，真正做到了<code>kubernetes native</code>。而底层基于envoy进行流量代理，也让人不需要太担心性能问题。对于路由、加密、基础认证、链路跟踪等场景，可尝试使用。而对于像<code>custom filter</code>、<code>rbac</code>、<code>advanced rate limiting</code>等场景有需求的用户，使用pro版本可满足要求。本人也与Ambassador开发团队进行了联系，遗憾的是Ambassador目前在国内尚未有reseller，若使用pro版，后期的维护支持也是需要考虑的内容。</p>
<h3 id="参考文献">参考文献</h3>
<ul>
<li><a href="https://www.getambassador.io/">https://www.getambassador.io</a></li>
<li>Using Ambassador to build Cloud-Native Applications - Steve Flanders, Omnition @ KubeCon 2019, Shanghai</li>
</ul>

        
                
        
              <hr>
              <ul class="pager">
                  
                  <li class="previous">
                      <a href="/post/deep-dive-into-cilium-multi-cluster/" data-toggle="tooltip" data-placement="top" title="深入了解Cilium多集群">&larr; Previous Post</a>
                  </li>
                  
                  
                  <li class="next">
                      <a href="/post/use-kubernetes-to-build-microservices/" data-toggle="tooltip" data-placement="top" title="使用spring boot&#43;kubernetes构建完整微服务平台">Next Post &rarr;</a>
                  </li>
                  
              </ul>
  
              

<div id="gitalk-container"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">
<script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<script src="/js/md5.min.js"></script>
<script>
	const gitalk = new Gitalk({
	  clientID: 'aff2580d8cc58af83367',
	  clientSecret: '747547f5f87fcc5145b847ab76a498d7e501319f',
	  repo: 'comment',
	  owner: 'shinji3887',
	  admin: ['shinji3887'],
	  id: md5(location.pathname),      
	  distractionFreeMode: false  
	})

	gitalk.render('gitalk-container')
</script>


            </div>
            
            <div class="
                col-lg-8 col-lg-offset-2
                col-md-10 col-md-offset-1
                sidebar-container">

                
                <section>
                    <hr class="hidden-sm hidden-xs">
                    <h5><a href="/tags/">FEATURED TAGS</a></h5>
                    <div class="tags">
                     
                    
                        
                            <a href="/tags/api-gateway" title="api-gateway">
                                api-gateway
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/cloud-native" title="cloud-native">
                                cloud-native
                            </a>
                        
                    
                        
                            <a href="/tags/devops" title="devops">
                                devops
                            </a>
                        
                    
                        
                            <a href="/tags/docker" title="docker">
                                docker
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/istio" title="istio">
                                istio
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/kubernetes" title="kubernetes">
                                kubernetes
                            </a>
                        
                    
                        
                            <a href="/tags/microservice" title="microservice">
                                microservice
                            </a>
                        
                    
                        
                    
                        
                    
                        
                    
                        
                    
                        
                            <a href="/tags/restful" title="restful">
                                restful
                            </a>
                        
                    
                        
                    
                        
                            <a href="/tags/servicemesh" title="servicemesh">
                                servicemesh
                            </a>
                        
                    
                        
                            <a href="/tags/spring-cloud" title="spring-cloud">
                                spring-cloud
                            </a>
                        
                    
                        
                            <a href="/tags/vue" title="vue">
                                vue
                            </a>
                        
                    
                        
                    
                        
                    
                    </div>
                </section>

                
                <hr>
                <h5>FRIENDS</h5>
                <ul class="list-inline">
                    
                        <li><a target="_blank" href="https://skyao.io/">小剑的博客</a></li>
                    
                        <li><a target="_blank" href="https://zhaohuabing.com/">huabing的博客</a></li>
                    
                        <li><a target="_blank" href="http://blog.didispace.com/">程序猿DD的博客</a></li>
                    
                </ul>
            </div>
        </div>
    </div>
</article>




<footer>
    <div class="container">
        <div class="row">
            <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
                <ul class="list-inline text-center">
                   
                   <li>
                       <a href="" rel="alternate" type="application/rss+xml" title="L&#39;s Blog" >
                           <span class="fa-stack fa-lg">
                               <i class="fa fa-circle fa-stack-2x"></i>
                               <i class="fa fa-rss fa-stack-1x fa-inverse"></i>
                           </span>
                       </a>
                   </li>
                   
                    
                    <li>
                        <a href="mailto:18016380795@163.com">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-envelope fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    
                    
                    

                    

		    
                    
                    <li>
                        <a target="_blank" href="/link%20of%20wechat%20QR%20code%20image">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-wechat fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    <li>
                        <a target="_blank" href="https://github.com/shinji3887">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-github fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                    
                    <li>
                        <a target="_blank" href="https://www.linkedin.com/in/lupeier">
                            <span class="fa-stack fa-lg">
                                <i class="fa fa-circle fa-stack-2x"></i>
                                <i class="fa fa-linkedin fa-stack-1x fa-inverse"></i>
                            </span>
                        </a>
                    </li>
		    
                </ul>
		<p class="copyright text-muted">
                    Copyright &copy; L&#39;s Blog , 2019
                    <br>
                    <br>
                    <a href="http://icp.chinaz.com/info?q=lupeier.com" target="_blank">备案号：沪ICP备19022667号-1</a>                    
                </p>
            </div>
        </div>
    </div>
</footer>



<script>
    function async(u, c) {
      var d = document, t = 'script',
          o = d.createElement(t),
          s = d.getElementsByTagName(t)[0];
      o.src = u;
      if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
      s.parentNode.insertBefore(o, s);
    }
</script>






<script>
    
    if($('#tag_cloud').length !== 0){
        async("/js/jquery.tagcloud.js",function(){
            $.fn.tagcloud.defaults = {
                
                color: {start: '#bbbbee', end: '#0085a1'},
            };
            $('#tag_cloud a').tagcloud();
        })
    }
</script>


<script>
    async("/js/fastclick.js", function(){
        var $nav = document.querySelector("nav");
        if($nav) FastClick.attach($nav);
    })
</script>


<script>
    (function(){
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https'){
       bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
      }
      else{
      bp.src = 'http://push.zhanzhang.baidu.com/push.js';
      }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>







</body>
</html>
